package com.namo.cchapi.service.impl;

import cn.hutool.core.convert.Convert;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.namo.cchapi.config.RestTemplateConfig;
import com.namo.cchapi.entity.*;
import com.namo.cchapi.service.RedisService;
import com.namo.cchapi.service.WechatService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.http.HttpEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author WangXin
 * @date 2021/4/8 11:02
 */
@Service
@Slf4j
@RefreshScope
public class WechatServiceImpl implements WechatService {
    private static final String GRANT_TYPE_AUTH = "client_credential";
    private static final String GRANT_TYPE_USER = "authorization_code";
    private static final String ACCESS_TOKEN = "access_token";
    public static final String OPEN_ID = "openid";
    public static final String ERR_CODE="errcode";

    @Value("${wechat.appid}")
    private String appId;
    @Value("${wechat.secret}")
    private String secret;
    @Autowired
    RestTemplate restTemplate;
    @Autowired
    RedisService redisService;
    @Autowired
    Gson gson;

    /**
     * 获取微信access_token
     *
     * @return
     * @throws Exception
     */
    public WechatAuthEntity getAccessToken() throws Exception {
        WechatAuthEntity wechatAuthEntity = null;
        wechatAuthEntity = (WechatAuthEntity) redisService.get("cch:wechat-auth");
        //redis命中场景
        if (wechatAuthEntity != null) {
            Long nowTime = System.currentTimeMillis();
            Long createTime = wechatAuthEntity.getCreateTime();
            //缓存未过期
            if (nowTime < createTime + wechatAuthEntity.getExpiresIn()) {
                log.info("缓存命中-未过期-返回数据");
                return wechatAuthEntity;
            } else {
                log.info("缓存命中-过期");
            }
        }
        log.info("重新获取-微信access_token");
        //构造请求参数
        Map<String, String> requestParam = new HashMap<>();
        requestParam.put("appid", appId);
        requestParam.put("secret", secret);
        requestParam.put("grant_type", GRANT_TYPE_AUTH);
        //发送请求
        ResponseEntity<String> stringResponseEntity = restTemplate.postForEntity("https://api.weixin.qq.com/cgi-bin/token?grant_type={grant_type}&appid={appid}&secret={secret}", null, String.class, requestParam);
        JsonObject jsonObject = gson.fromJson(stringResponseEntity.getBody(), JsonObject.class);
        //判断获取错误并抛出异常
        if (jsonObject.has(ACCESS_TOKEN) == false) {
            log.error("获取微信access_token错误：{}" + jsonObject);
            throw new Exception("获取微信access_token错误");
        }
        log.info("重新获取-微信access_token-成功");
        wechatAuthEntity = gson.fromJson(jsonObject, WechatAuthEntity.class);
        //修改时间单位为ms，微信官方提供的时间是秒
        wechatAuthEntity.setExpiresIn(wechatAuthEntity.getExpiresIn() * 1000);
        wechatAuthEntity.setCreateTime(System.currentTimeMillis());
        redisService.set("cch:wechat-auth", wechatAuthEntity);
        return wechatAuthEntity;
    }

    /**
     * 获取用户开放信息
     *
     * @param jsCode 传入code
     * @return
     */
    @Override
    public WechatUserOpenEntity getUserOpen(String jsCode) throws Exception {
        //构造请求参数
        Map<String, String> requestParam = new HashMap<>();
        requestParam.put("appid", appId);
        requestParam.put("secret", secret);
        requestParam.put("js_code", jsCode);
        requestParam.put("grant_type", GRANT_TYPE_USER);
        //发送请求
        ResponseEntity<String> stringResponseEntity = restTemplate.postForEntity("https://api.weixin.qq.com/sns/jscode2session?appid={appid}&secret={secret}&js_code={js_code}&grant_type={grant_type}", null, String.class, requestParam);
        JsonObject jsonObject = gson.fromJson(stringResponseEntity.getBody(), JsonObject.class);
        //判断获取错误并抛出异常
        if (jsonObject.has(OPEN_ID) == false) {
            log.error("获取微信用户开放信息错误：{}" + jsonObject);
            throw new Exception("获取微信用户开放信息错误");
        }
        WechatUserOpenEntity wechatUserOpenEntity = gson.fromJson(jsonObject, WechatUserOpenEntity.class);
        log.info("获取微信用户开放信息-成功-------=>" + wechatUserOpenEntity);
        return wechatUserOpenEntity;
    }

    /**
     * 获取消息模板列表
     *
     * @return
     * @throws Exception
     */
    @Override
    public List<WechatMessageTemplateEntity> getTemplateList() throws Exception {
        //构造请求参数
        Map<String, String> requestParam = new HashMap<>();
        requestParam.put("access_token", this.getAccessToken().getAccessToken());
        //发送请求
        ResponseEntity<String> stringResponseEntity = restTemplate.getForEntity("https://api.weixin.qq.com/wxaapi/newtmpl/gettemplate?access_token={access_token}", String.class, requestParam);
        JsonObject jsonObject = gson.fromJson(stringResponseEntity.getBody(), JsonObject.class);
        //判断返回的信息是否包含errcode，判断是否为0
        if (jsonObject.has(ERR_CODE) == false || jsonObject.get("errcode").getAsInt() != 0 ){
            log.error("获取消息模板失败,微信服务器返回错误信息："+jsonObject);
            throw new Exception("获取消息模板失败："+jsonObject.get("errmsg").getAsString());
        }
        List<WechatMessageTemplateEntity> wechatMessageTemplateEntities = new ArrayList<>();
        //遍历，获取data的值
        JsonArray data = jsonObject.getAsJsonArray("data");
        for (int i = 0; i < data.size(); i++) {
            WechatMessageTemplateEntity wechatMessageTemplateEntity = new WechatMessageTemplateEntity();
            wechatMessageTemplateEntity = gson.fromJson(data.get(i), WechatMessageTemplateEntity.class);
            wechatMessageTemplateEntity.setContents(getContents(data.get(i).getAsJsonObject().get("content").toString().replace("\"", "")));
            wechatMessageTemplateEntities.add(wechatMessageTemplateEntity);
        }
        return wechatMessageTemplateEntities;
    }


    /**
     * 发送消息
     * @param wechatMessageEntity
     * @return
     * @throws Exception
     */
    @Override
    public WechatMessageEntity sendMessage(WechatMessageEntity wechatMessageEntity) throws Exception {
        if (wechatMessageEntity == null){
            log.error("请求参数为空,返回错误");
            throw new Exception("参数为空！");
        }
        //构造请求参数,附带access_token
        Map<String, String> requestParam = new HashMap<>();
        requestParam.put("access_token", this.getAccessToken().getAccessToken());
        //发送请求
        ResponseEntity<String> stringResponseEntity = restTemplate.postForEntity("https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token={access_token}", Convert.strToUnicode(gson.toJson(wechatMessageEntity)), String.class, requestParam);
        JsonObject jsonObject = gson.fromJson(stringResponseEntity.getBody(), JsonObject.class);
        //判断返回的信息是否包含errcode，或者是否为0
        if (jsonObject.has(ERR_CODE) == false || jsonObject.get("errcode").getAsInt() != 0 ){
            log.error("发送消息失败,微信服务器返回错误，信息："+jsonObject);
            throw new Exception("发送消息失败："+jsonObject.get("errmsg").getAsString());
        }
        log.info("发送消息成功=>"+wechatMessageEntity);
        return wechatMessageEntity;
    }


    /**
     * 解析content字符串  输入：会议时间:{{date2.DATA}}\n会议地点:{{thing1.DATA}}\n
     *
     * @param contents [WechatMessageTemplateContent(title=会议时间, content=date2),WechatMessageTemplateContent(title=会议地点, content=thing1)]
     * @return
     */
    private static List<WechatMessageTemplateContent> getContents(String contents) {
        List<WechatMessageTemplateContent> wechatMessageTemplateContents = new ArrayList<>();
        //分割每个单独字符串
        String[] strings = contents.split("\\\\n");
        for (int i = 0; i < strings.length; i++) {
            String[] split = strings[i].split(":");
            WechatMessageTemplateContent wechatMessageTemplateContent = new WechatMessageTemplateContent();
            wechatMessageTemplateContent.setTitle(split[0]);
            //替换掉无用字符串
            wechatMessageTemplateContent.setName(split[1].replace("{{", "").replace(".DATA}}", ""));
            wechatMessageTemplateContents.add(wechatMessageTemplateContent);
        }
        return wechatMessageTemplateContents;
    }
}
